using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using TerritoryGame.Domain.Entities;
using TerritoryGame.Domain.Repositories;

namespace TerritoryGame.Infrastructure.Persistence.Repositories;

public class GameRoomRepository : IGameRoomRepository
{
    private readonly GameDbContext _context;

    public GameRoomRepository(GameDbContext context)
    {
        _context = context;
    }

    public async Task<GameRoom?> GetByIdAsync(Guid id)
    {
        return await _context.GameRooms
            .Include(r => r.Players)
            .FirstOrDefaultAsync(r => r.Id == id);
    }

    public async Task<GameRoom> AddAsync(GameRoom room)
    {
        _context.GameRooms.Add(room);
        await _context.SaveChangesAsync();
        return room;
    }

    public async Task<GameRoom> UpdateAsync(GameRoom room)
    {
        try
        {
            _context.GameRooms.Update(room);
            await _context.SaveChangesAsync();
            return room;
        }
        catch (DbUpdateConcurrencyException ex)
        {
            // 处理并发冲突
            var entry = ex.Entries.Single();
            var databaseValues = await entry.GetDatabaseValuesAsync();
            
            if (databaseValues == null)
            {
                // 实体已被删除
                throw new InvalidOperationException("Room has been deleted");
            }
            
            // 重新加载实体并重试
            var databaseRoom = (GameRoom)databaseValues.ToObject();
            _context.Entry(room).CurrentValues.SetValues(databaseValues);
            
            // 重新应用更改
            _context.GameRooms.Update(room);
            await _context.SaveChangesAsync();
            return room;
        }
    }

    public async Task DeleteAsync(Guid id)
    {
        var room = await _context.GameRooms.FindAsync(id);
        if (room != null)
        {
            _context.GameRooms.Remove(room);
            await _context.SaveChangesAsync();
        }
    }

    public async Task<IEnumerable<GameRoom>> GetWaitingRoomsAsync()
    {
        return await _context.GameRooms
            .Include(r => r.Players)
            .Where(r => r.Status == GameStatus.Waiting)
            .ToListAsync();
    }

    public async Task<GameRoom?> GetByPasswordAsync(string password)
    {
        return await _context.GameRooms
            .Include(r => r.Players)
            .FirstOrDefaultAsync(r => r.Password == password);
    }

    public async Task<GameRoom?> GetByCodeAsync(string roomCode)
    {
        return await _context.GameRooms
            .Include(r => r.Players)
            .FirstOrDefaultAsync(r => r.RoomCode == roomCode);
    }

    public async Task<bool> AddPlayerToRoomAsync(Guid roomId, Player player, string? password = null)
    {
        try
        {
            var room = await _context.GameRooms
                .Include(r => r.Players)
                .FirstOrDefaultAsync(r => r.Id == roomId);

            if (room == null) return false;

            // 检查玩家是否已存在
            if (room.Players.Any(p => p.Id == player.Id))
            {
                return true; // 玩家已存在，视为成功
            }

            // 检查是否可以加入房间（只有在提供了密码参数时才进行密码验证）
            if (password != null && !room.CanJoin(password, player.Id))
            {
                // 添加调试信息
                Console.WriteLine($"Cannot join room: Status={room.Status}, PlayerCount={room.Players.Count}, MaxPlayers={room.MaxPlayers}, HasPassword={!string.IsNullOrEmpty(room.Password)}, ProvidedPassword={password}, PlayerId={player.Id}, CreatedBy={room.CreatedBy}");
                return false;
            }
            
            // 如果没有提供密码参数，跳过密码验证，直接检查基本条件
            if (password == null)
            {
                if (room.Status != GameStatus.Waiting || room.Players.Count >= room.MaxPlayers)
                {
                    return false;
                }
            }

            // 添加玩家（跳过密码验证，因为已经在上面验证过了）
            room.AddPlayer(player, true);

            await _context.SaveChangesAsync();
            return true;
        }
        catch (DbUpdateConcurrencyException)
        {
            // 并发冲突，重试一次
            try
            {
                var room = await _context.GameRooms
                    .Include(r => r.Players)
                    .FirstOrDefaultAsync(r => r.Id == roomId);

                if (room == null) return false;

                // 再次检查玩家是否已存在
                if (room.Players.Any(p => p.Id == player.Id))
                {
                    return true;
                }

                // 再次检查是否可以加入房间（如果提供了密码，则进行密码验证）
                if (password != null && !room.CanJoin(password, player.Id))
                {
                    return false;
                }

                room.AddPlayer(player, true);

                await _context.SaveChangesAsync();
                return true;
            }
            catch
            {
                return false;
            }
        }
    }

    public async Task<bool> DeleteRoomAsync(Guid roomId)
    {
        try
        {
            var room = await _context.GameRooms
                .Include(r => r.Players)
                .FirstOrDefaultAsync(r => r.Id == roomId);

            if (room == null) return false;

            // 只有当房间为空时才删除
            if (room.Players.Count == 0)
            {
                _context.GameRooms.Remove(room);
                await _context.SaveChangesAsync();
                return true;
            }

            return false; // 房间不为空，不删除
        }
        catch (Exception)
        {
            return false;
        }
    }

    public async Task<bool> RemovePlayerFromRoomAsync(Guid roomId, Guid playerId)
    {
        var room = await _context.GameRooms
            .Include(r => r.Players)
            .FirstOrDefaultAsync(r => r.Id == roomId);
        if (room == null) return false;

        var player = room.Players.FirstOrDefault(p => p.Id == playerId);
        if (player == null) return true; // 视为移除成功

        room.RemovePlayer(playerId);
        await _context.SaveChangesAsync();
        return true;
    }
public async Task<bool> DeleteRoomByCodeAsync(string roomCode)
{
    var room = await _context.GameRooms
        .Include(r => r.Players) // 确保导航属性名为 Players
        .FirstOrDefaultAsync(r => r.RoomCode == roomCode);
    if (room != null)
    {

        // 删除所有关联玩家
        _context.Players.RemoveRange(room.Players);


        _context.GameRooms.Remove(room);
        await _context.SaveChangesAsync();
        return true;
    }
    return false;
}
    
}
